/*****************************************************************************
 *  ENTROPY - emerging network to reduce orwellian potency yield
 *
 *  Copyright (C) 2002 Juergen Buchmueller <pullmoll@stop1984.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software Foundation,
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 *	$Id: i18n.c,v 1.2 2005/07/12 23:12:29 pullmoll Exp $
 *****************************************************************************/
#include "osd.h"
#include "memalloc.h"
#include "tools.h"
#include "unicode.h"
#include "i18n.h"
#include "logger.h"

#define	LINESIZE	4096
char language[2+1] = "de";
char langpath[MAXPATHLEN] = ".";
l10n_t *l10n = NULL;

/* translate src_text from src_charset into dst_charset */
const char *translate(const char *src_text,
	const char *src_charset, const char *dst_charset)
{
#undef	BUFSIZE
#undef	BUFNUM
#define	BUFSIZE	1024
#define	BUFNUM	16
	static char buff[BUFNUM][BUFSIZE];
	static int which = 0;
	const fontmap_t *src_map;
	const char *src;
	const fontmap_t *dst_map;
	size_t offs, size = BUFSIZE;
	uint32_t ucs;
	uint8_t ch;

	which = (which + 1) % BUFNUM;

	src_map = wcmapset(src_charset);
	dst_map = wcmapset(dst_charset);
	for (src = src_text, offs = 0; *src; src++) {
		ucs = wcmapcode(src_map, (uint8_t)*src);
		if (offs + 16 >= size) {
			break;
		}
		if (NULL == dst_map) {
			offs += wcencode(&buff[which][offs], ucs, WC_UTF8);
		} else if (0 == (ch = mapencode(dst_map, ucs))) {
			offs += pm_spprintf(&buff[which][offs], buff[which], size,
				"&#%u;", ucs);
		} else {
			buff[which][offs++] = ch;
		}
	}
	buff[which][offs] = '\0';
	return buff[which];
}

const char *localize(const char *languages, const char *charset,
	const char *english)
{
	char toke[128], *src;
	char *lang, *eol;
	l10n_t *l;
	FUN("localize");

	pm_snprintf(toke, sizeof(toke), "%s", languages);
	src = toke;
	while (NULL != src && *src != '\0') {
		eol = strchr(src, ',');
		if (NULL == eol)
			eol = strchr(src, '\r');
		if (NULL == eol)
			eol = strchr(src, '\n');
		if (NULL == eol)
			eol = src + strlen(src);
		else
			*eol++ = '\0';
		lang = toke;
		src = eol;
		if (*lang == '\0')
			break;
		while (*lang && isspace(*lang))
			lang++;
		if (0 == strncmp(lang, "en", 2))
			continue;
		for (l = l10n; NULL != l; l = l->next) {
			if (0 == strcmp(l->lang, lang)) {
				if (0 == strcasecmp(l->english, english)) {
					return translate(l->localized, l->charset, charset);
				}
			}
		}
	}
	/* return the original (english) string */
	return translate(english, "iso-8859-1", charset);
}

static int i18n_add_lang(const char *languages)
{
	char *toke = xstrdup(languages);
	char *lang = NULL;
	char *english = NULL;
	char *localized = NULL;
	char *filename = NULL;
	char *semi;
	char *eol;
	l10n_t *l;
	FILE *fp = NULL;
	int rc = 0;
	FUN("i18n_add_lang");

	semi = strchr(toke, ';');
	if (NULL != semi) {
		*semi-- = '\0';
		while (semi > toke && *semi == ' ')
			*semi-- = '\0';
	}
	lang = toke;
	while (*lang == ' ')
		lang++;

	pm_asprintf(&filename, "%s%s/%s.lo",
		langpath, lang, g_conf->progname);
	fp = fopen(filename, "r");
	if (NULL == fp) {
		LOG(L_ERROR,("No l10n for lang '%s' in '%s'\n",
			lang, filename));
		rc = -1;
		goto bailout;
	}

	english = xcalloc(LINESIZE, 1);
	localized = xcalloc(LINESIZE, 1);
	while (!feof(fp)) {
		if (NULL == fgets(english, LINESIZE, fp)) {
			break;
		}
		if (NULL != (eol = strchr(english, '\n')))
			*eol = '\0';
		if (NULL != (eol = strchr(english, '\r')))
			*eol = '\0';
		if (NULL == fgets(localized, LINESIZE, fp)) {
			LOG(L_ERROR,("End of file when expecting '%s' l10n" \
				" for '%s' in '%s'\n",
				lang, english, filename));
			rc = -1;
			goto bailout;
		}
		if (NULL != (eol = strchr(localized, '\n')))
			*eol = '\0';
		if (NULL != (eol = strchr(localized, '\r')))
			*eol = '\0';
		l = (l10n_t *)xcalloc(1, sizeof(l10n_t));
		l->next = l10n;
		l->lang = xstrdup(lang);
		l->english = xstrdup(english);
		l->localized = xstrdup(localized);
		l10n = l;
		LOG(L_DEBUG,("'%s' l10n '%s'\n", l->english, l->localized));
	}
	LOG(L_NORMAL,("Loaded l10n for lang '%s'\n", lang));

bailout:
	if (NULL != fp) {
		fclose(fp);
		fp = NULL;
	}
	xfree(english);
	xfree(localized);
	xfree(toke);
	xfree(filename);
	return rc;
}

int i18n(const char *path)
{
	int rc = 0;
	FUN("i18n_init");
	pm_snprintf(langpath, sizeof(langpath), "%s", path);

	/* I'll add a language= setting to the config later... */
	i18n_add_lang(language);

	return rc;
}
